home *** CD-ROM | disk | FTP | other *** search
- # include <stdio.h>
- # include "constants.h"
- # include "globals.h"
- # include <sccs.h>
-
- SCCSID(@(#)cvar.c 8.1 12/31/84)
-
- /*
- ** CVAR -- routines to manipulate the c variable trees
- **
- ** C variable trees are binary trees of cvar structs,
- ** with the c_left < c_right with respect to c_id.
- */
- /*
- ** DECL_CVAR -- Declare a C variable
- **
- ** Parameters:
- ** name -- identifier string (makes its own copy for the tree)
- ** type
- ** indir_level -- level of indirection of declaration
- ** (- 1 if string)
- ** block_level -- 0 - global, else local var
- **
- ** Returns:
- ** none
- **
- ** Side Effects:
- ** allocates a cvar node, and a copy of name, may put a node
- ** in a cvar tree (if not previously declared).
- **
- ** Called By:
- ** the c_variable productions of the parser [grammar.y]
- */
-
-
- decl_cvar(name, type, indir_level, block_level)
- char *name;
- int type;
- int indir_level;
- int block_level;
- {
- register struct cvar *bad_node;
- struct cvar *dec_var();
-
- if (bad_node = dec_var(name, type, indir_level, block_level,
- &C_locals, &C_globals))
- {
- yysemerr("re-declared identifier", bad_node->c_id);
- xfree(bad_node->c_id);
- xfree(bad_node);
- }
- }
-
- /*
- ** DECL_FIELD -- Declare a structures field
- **
- ** Same as decl_cvar() for fields within C records (structs).
- ** NOTE : if a !0 is returned from dec_var() (i.e. the field
- ** was already declared) the storage for that node is freed
- ** but no error has been comitted, as fields may be re-declared.
- */
-
- decl_field(name, type, indir_level, block_level)
- char *name;
- int type;
- int indir_level;
- int block_level;
- {
- register struct cvar *bad_node;
- struct cvar *dec_var();
-
- if (bad_node = dec_var(name, type, indir_level, block_level,
- &F_locals, &F_globals))
- {
- xfree(bad_node->c_id);
- xfree(bad_node);
- }
- }
- /*
- ** DEC_VAR -- declare a C var or field.
- **
- ** Parameters:
- ** same as decl_cvar() & decl_field plus
- ** the local and global tree variables.
- **
- ** Returns:
- ** 0 -- successful
- ** other -- cvar node pointer that couldn't be entered
- ** to tree
- */
-
- struct cvar *
- dec_var(name, type, indir_level, block_level, local_tree, global_tree)
- char *name;
- int type, indir_level, block_level;
- struct cvar **local_tree, **global_tree;
- {
- register struct cvar *cvarp;
- register i;
- char *salloc();
-
- cvarp = (struct cvar *)nalloc(sizeof *cvarp);
- if (!cvarp)
- {
- yysemerr("unable to allocate space for a variable", name);
- return (0);
- }
- if (!(cvarp->c_id = salloc(name)))
- {
- yysemerr("no space for variable name", name);
- xfree(cvarp);
- return (0);
- }
- cvarp->c_type = type;
- cvarp->c_indir = indir_level;
- cvarp->c_left = cvarp->c_right = 0;
- i = c_enter(cvarp, block_level > 0 ? local_tree : global_tree);
- return (i ? 0 : cvarp);
- }
- /*
- ** C_ENTER -- Enter a cvar node in a cvar tree
- **
- ** Parameters:
- ** node -- the cvar node to insert
- ** root -- a pointer to the root pointer
- **
- ** Returns:
- ** 1 -- if successful
- ** 0 -- otherwise (node of same name existed
- **
- ** Side Effects:
- ** If a node of that name didn't exist one is inserted
- **
- ** Called By:
- ** dec_var()
- */
-
- c_enter(node, root)
- struct cvar *node;
- struct cvar **root;
- {
- register char *name;
- register struct cvar *n, *r;
-
- r = *root;
- n = node;
- name = n->c_id;
- if (!r)
- {
- *root = n;
- return (1);
- }
- for (;;)
- {
- switch (scompare(name, 0, r->c_id, 0))
- {
-
- case -1 :
- if (!r->c_left)
- {
- r->c_left = n;
- return (1);
- }
- r = r->c_left;
- break;
-
- case 0 :
- yysemerr("identifier re-declared", name);
- xfree(name);
- xfree(n);
- return (0);
-
- case 1 :
- if (!r->c_right)
- {
- r->c_right = n;
- return (1);
- }
- r = r->c_right;
- break;
- }
- }
- }
-
-
- /*
- ** GET_VAR -- get a cvar node from a local_tree, global_tree pair
- ** searching first through the local then the global.
- **
- ** Parameters:
- ** id -- c_id key
- ** local_tree -- first tree
- ** global_tree -- secomd tree to search
- **
- ** Returns:
- ** 0 -- if no node by that name
- ** otherwise -- pointer to the node
- */
-
-
- struct cvar *get_var(id, local_tree, global_tree)
- char *id;
- struct cvar *local_tree, *global_tree;
- {
- register char *name;
- register struct cvar *tree, *node;
- char flag;
-
- flag = 0;
- name = id;
- tree = local_tree;
- for ( ; ; )
- {
- for (node = tree; node; )
- {
- switch (scompare(name, 0, node->c_id, 0))
- {
-
- case -1 :
- if (!node->c_left)
- break;
- else
- node = node->c_left;
- continue;
-
- case 0 :
- return (node);
-
- case 1 :
- if (!node->c_right)
- break;
- else
- node = node->c_right;
- continue;
- }
- break;
- }
- if (!flag)
- {
- flag += 1;
- tree = global_tree;
- }
- else
- return (0);
- }
- }
- /*
- ** GETCVAR -- get the cvar node for a given identifier
- ** Looks first in C_locals, then in C_globals.
- **
- ** Parameters:
- ** id -- name of cvar to look for
- **
- ** Returns:
- ** adress of cvar node if found
- ** 0 -- otherwise
- **
- ** Requires:
- ** C_locals & C_globals -- to search them
- */
-
- struct cvar *
- getcvar(id)
- char *id;
- {
- return (get_var(id, C_locals, C_globals));
- }
-
- /*
- ** GETFIELD -- Same as getcvar() for structure fields
- */
-
- struct cvar *
- getfield(id)
- char *id;
- {
- return (get_var(id, F_locals, F_globals));
- }
-
-
- /*
- ** FREECVAR & F_CVAR -- Free up storage in a cvar tree
- **
- ** Freecvar calls f_cvar to free storage for a tree, then
- ** 0's out the root pointer passed it.
- */
-
- freecvar(rootp)
- struct cvar **rootp;
- {
- f_cvar(*rootp);
- *rootp = 0;
- }
-
- f_cvar(root)
- struct cvar *root;
- {
- if (root)
- {
- f_cvar(root->c_left);
- f_cvar(root->c_right);
- xfree(root->c_id);
- xfree(root);
- }
- }
-